home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / drivers.arc / HEAD.ASM < prev    next >
Encoding:
Assembly Source File  |  1988-10-28  |  12.7 KB  |  625 lines

  1. ;/* PC/FTP Packet Driver source, conforming to version 1.05 of the spec
  2. ;*  Russell Nelson, Clarkson University.  July 20, 1988
  3. ;*  Portions (C) Copyright 1988 Russell Nelson
  4. ;*
  5. ;*  Permission is granted to any individual or institution to use, copy,
  6. ;*  modify, or redistribute this software and its documentation provided
  7. ;*  this notice and the copyright notices are retained.  This software may
  8. ;*  not be distributed for profit, either in original form or in derivative
  9. ;*  works.  Russell Nelson makes no representations about the suitability
  10. ;*  of this software for any purpose.  RUSSELL NELSON GIVES NO WARRANTY,
  11. ;*  EITHER EXPRESS OR IMPLIED, FOR THE PROGRAM AND/OR DOCUMENTATION
  12. ;*  PROVIDED, INCLUDING, WITHOUT LIMITATION, WARRANTY OF MERCHANTABILITY
  13. ;*  AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE.
  14. ;*/
  15.  
  16.  
  17. code    segment byte public
  18.     assume    cs:code, ds:code
  19.  
  20.     public    phd_environ
  21.     org    2ch
  22. phd_environ    dw    ?
  23.  
  24.     public    phd_dioa
  25.     org    80h
  26. phd_dioa    label    byte
  27.  
  28.  
  29. ;we use our program header as stack space.
  30. stack    label    byte
  31.  
  32.     org    100h
  33. start:
  34.     jmp    start_1
  35.     extrn    start_1: near
  36.  
  37. ;
  38. ;  Packet Driver Error numbers
  39. BAD_HANDLE    equ    1        ;invalid handle number
  40. NO_CLASS    equ    2        ;no interfaces of specified class found
  41. NO_TYPE        equ    3        ;no interfaces of specified type found
  42. NO_NUMBER    equ    4        ;no interfaces of specified number found
  43. BAD_TYPE    equ    5        ;bad packet type specified
  44. NO_MULTICAST    equ    6        ;this interface does not support
  45. CANT_TERMINATE    equ    7        ;this packet driver cannot terminate
  46. BAD_MODE    equ    8        ;an invalid receiver mode was specified
  47. NO_SPACE    equ    9        ;operation failed because of insufficient
  48. TYPE_INUSE    equ    10        ;the type had previously been accessed,
  49. BAD_COMMAND    equ    11        ;the command was out of range, or not
  50. CANT_SEND    equ    12        ;the packet couldn't be sent (usually
  51.  
  52.  
  53.     extrn    int_no: byte
  54.     public    packet_int_no, is_at
  55. packet_int_no    db    ?,?        ; interrupt to communicate.
  56. is_at        dw    ?        ; =1 if we're on an AT.
  57.  
  58. functions    label    word
  59.     dw    f_driver_info        ;function 1
  60.     dw    f_access_type
  61.     dw    f_release_type
  62.     dw    f_send_pkt
  63.     dw    f_terminate
  64.     dw    f_get_address
  65.     dw    f_reset_interface    ;function 7
  66.     dw    f_set_rcv_mode        ;function 20
  67.     dw    f_get_rcv_mode
  68.     dw    f_set_multicast_list
  69.     dw    f_get_multicast_list
  70.     dw    f_get_statistics    ;function 24
  71.  
  72.  
  73.     extrn    driver_class: byte
  74.     extrn    driver_type: byte
  75.     extrn    driver_name: byte
  76.  
  77.     extrn    send_pkt: near
  78.     extrn    get_address: near
  79.     extrn    reset_interface: near
  80.     extrn    recv: near
  81.  
  82.  
  83. MAX_P_LEN    equ    8        ;leave plenty of room.
  84.  
  85. per_handle    struc
  86. in_use        db    ?        ;non-zero if this handle is in use.
  87. packet_type    db    MAX_P_LEN dup(?);associated packet type.
  88. packet_type_len    dw    ?        ;associated packet type length.
  89. receiver    dd    ?        ;receiver handler.
  90. per_handle    ends
  91.  
  92. max_handle    equ    8
  93. handles        db    max_handle*(size per_handle) dup(0)
  94. end_handles    label    byte
  95.  
  96. free_handle    dw    ?        ;->a handle not in use.
  97. found_handle    dw    ?        ;->the handle for our packet.
  98.  
  99. savess        dw    ?        ;saved during the stack swap.
  100. savesp        dw    ?
  101.  
  102. regs    struc
  103. _ES    dw    ?
  104. _DS    dw    ?
  105. _BP    dw    ?
  106. _DI    dw    ?
  107. _SI    dw    ?
  108. _DX    dw    ?
  109. _CX    dw    ?
  110. _BX    dw    ?
  111. _AX    dw    ?
  112. _IP    dw    ?
  113. _CS    dw    ?
  114. _F    dw    ?        ;flags, Carry flag is bit 0.
  115. regs    ends
  116.  
  117.  
  118. bytes    struc
  119.     dw    ?
  120.     dw    ?
  121.     dw    ?
  122.     dw    ?
  123.     dw    ?
  124. _DL    db    ?
  125. _DH    db    ?
  126. _CL    db    ?
  127. _CH    db    ?
  128. _BL    db    ?
  129. _BH    db    ?
  130. _AL    db    ?
  131. _AH    db    ?
  132. bytes    ends
  133.  
  134. segmoffs    struc
  135. offs        dw    ?
  136. segm        dw    ?
  137. segmoffs    ends
  138.  
  139.  
  140.     public    our_isr, their_isr
  141. their_isr    dd    ?
  142.  
  143. our_isr:
  144.     jmp    our_isr_0        ;the required signature.
  145.     db    'PKT DRVR',0
  146.  
  147. statistics_list    label    dword
  148. packets_in    dw    ?,?
  149. packets_out    dw    ?,?
  150. bytes_in    dw    ?,?
  151. bytes_out    dw    ?,?
  152. errors_in    dw    ?,?
  153. errors_out    dw    ?,?
  154. packets_dropped    dw    ?,?        ;dropped due to no type handler.
  155.  
  156. linc    macro    n
  157.     local    a
  158.     inc    n            ;increment the low word
  159.     jne    a            ;go if not overflow
  160.     inc    n+2            ;increment the high word
  161. a:
  162.     endm
  163.  
  164.     public    count_in_err
  165. count_in_err:
  166.     assume    ds:nothing
  167.     linc    errors_in
  168.     ret
  169.  
  170.     public    count_out_err
  171. count_out_err:
  172.     assume    ds:nothing
  173.     linc    errors_out
  174.     ret
  175.  
  176. our_isr_0:
  177.     assume    ds:nothing
  178.     push    ax
  179.     push    bx
  180.     push    cx
  181.     push    dx
  182.     push    si
  183.     push    di
  184.     push    bp
  185.     push    ds
  186.     push    es
  187.     mov    bx,cs            ;set up ds.
  188.     mov    ds,bx
  189.     assume    ds:code
  190.     mov    bp,sp            ;we use bp to access the original regs.
  191.     and    _F[bp],not 1        ;start by clearing the carry flag.
  192.     mov    bl,ah            ;jump to the correct function.
  193.     mov    bh,0
  194.     cmp    bx,7            ;highest function is 7.
  195.     jbe    our_isr_3
  196.     cmp    bx,20
  197.     jb    our_isr_2
  198.     cmp    bx,24
  199.     ja    our_isr_2
  200.     sub    bx,20-7+1        ;map 20 right after 7.
  201. our_isr_3:
  202.     add    bx,bx            ;*2
  203.     jmp    functions-2[bx]        ;table starts at 1.
  204.  
  205. f_set_rcv_mode:
  206. f_get_rcv_mode:
  207. f_set_multicast_list:
  208. f_get_multicast_list:
  209. our_isr_2:
  210.     mov    dh,BAD_COMMAND
  211. our_isr_error:
  212.     mov    _DH[bp],dh
  213.     or    _F[bp],1        ;return their carry flag.
  214. our_isr_return:
  215.     pop    es
  216.     pop    ds
  217.     pop    bp
  218.     pop    di
  219.     pop    si
  220.     pop    dx
  221.     pop    cx
  222.     pop    bx
  223.     pop    ax
  224.     iret
  225.  
  226.  
  227. f_driver_info:
  228.     call    verify_handle
  229.     mov    _BX[bp],0        ;version 0.
  230.     mov    al,driver_class
  231.     mov    _CH[bp],al
  232.     mov    al,driver_type
  233.     cbw
  234.     mov    _DX[bp],ax
  235.     mov    _CL[bp],0        ;number zero.
  236.     mov    _DS[bp],ds
  237.     mov    _SI[bp],offset driver_name
  238.     mov    _AL[bp],2        ;extended driver
  239.     jmp    our_isr_return
  240.  
  241.  
  242. f_get_statistics:
  243.     call    verify_handle        ;just in case.
  244.     mov    _DS[bp],ds
  245.     mov    _SI[bp],offset statistics_list
  246.     jmp    our_isr_return
  247.  
  248.  
  249. access_type_class:
  250.     mov    dh,NO_CLASS
  251.     jmp    our_isr_error
  252.  
  253. access_type_type:
  254.     mov    dh,NO_CLASS
  255.     jmp    our_isr_error
  256.  
  257. access_type_number:
  258.     mov    dh,NO_NUMBER
  259.     jmp    our_isr_error
  260.  
  261. f_access_type:
  262.     mov    al,driver_class
  263.     cmp    _AL[bp],al        ;our class?
  264.     jne    access_type_class    ;no.
  265.     cmp    _BX[bp],-1        ;generic type?
  266.     je    access_type_2        ;yes.
  267.     mov    al,driver_type
  268.     cbw
  269.     cmp    _BX[bp],ax        ;our type?
  270.     jne    access_type_type    ;no.
  271. access_type_2:
  272.     cmp    _DL[bp],0        ;generic number?
  273.     je    access_type_3
  274.     cmp    _DL[bp],1        ;our number?
  275.     jne    access_type_number
  276. access_type_3:
  277.     cmp    _CX[bp],MAX_P_LEN    ;is the type length too long?
  278.     ja    access_type_inuse    ;yes - can't be ours.
  279. access_type_7:
  280.  
  281. ; now we do two things--look for an open handle, and check the existing
  282. ; handles to see if they're replicating a packet type.
  283.  
  284.     mov    free_handle,0        ;remember no free handle yet.
  285.     mov    bx,offset handles
  286. access_type_4:
  287.     cmp    [bx].in_use,0        ;is this handle in use?
  288.     je    access_type_5        ;no - don't check the type.
  289.     mov    es,_DS[bp]        ;get a pointer to their type.
  290.     mov    di,_SI[bp]
  291.     mov    cx,_CX[bp]
  292.     cmp    cx,[bx].packet_type_len    ;lengths equal?
  293.     jne    access_type_6        ;no - keep looking.
  294.     lea    si,[bx].packet_type
  295.     or    cx,cx            ;in case cx is zero.
  296.     repe    cmpsb
  297.     jne    short access_type_6    ;go look at the next one.
  298. access_type_inuse:
  299.     mov    dh,TYPE_INUSE
  300.     jmp    our_isr_error
  301. access_type_5:
  302.     cmp    free_handle,0        ;found a free handle yet?
  303.     jne    access_type_6        ;yes.
  304.     mov    free_handle,bx        ;remember a free handle
  305. access_type_6:
  306.     add    bx,(size per_handle)    ;go to the next handle.
  307.     cmp    bx,offset end_handles
  308.     jb    access_type_4
  309.  
  310.     mov    bx,free_handle        ;did we find a free handle?
  311.     or    bx,bx
  312.     je    access_type_handle    ;no - return error.
  313.  
  314.     mov    [bx].in_use,1        ;remember that we're using it.
  315.  
  316.     mov    ax,_DI[bp]        ;remember the receiver type.
  317.     mov    [bx].receiver.offs,ax
  318.     mov    ax,_ES[bp]
  319.     mov    [bx].receiver.segm,ax
  320.  
  321.     push    ds
  322.     mov    ax,ds
  323.     mov    es,ax
  324.     mov    ds,_DS[bp]        ;remember their type.
  325.     mov    si,_SI[bp]
  326.     mov    cx,_CX[bp]
  327.     mov    es:[bx].packet_type_len,cx    ;remember the length.
  328.     lea    di,[bx].packet_type
  329.     rep    movsb
  330.     pop    ds
  331.  
  332.     mov    _AX[bp],bx        ;return the handle to them.
  333.  
  334.     jmp    our_isr_return
  335.  
  336.  
  337. access_type_handle:
  338.     mov    dh,BAD_HANDLE
  339.     jmp    our_isr_error
  340.  
  341.  
  342. f_release_type:
  343.     call    verify_handle        ;mark this handle as being unused.
  344.     mov    [bx].in_use,0
  345.     jmp    our_isr_return
  346.  
  347.  
  348. f_send_pkt:
  349.     linc    packets_out
  350.     add    bytes_out.offs,cx    ;add up the received bytes.
  351.     adc    bytes_out.segm,0
  352.  
  353.     push    ds        ; set up proper ds for the buffer
  354.     mov    ds,_DS[bp]    ; address for buffer
  355. ;    mov    si,_SI[bp]
  356. ;    mov    cx,_CX[bp]    ; count of bytes
  357.  
  358.     call    send_pkt
  359.     pop    ds
  360.     jc    send_pkt_1
  361.     jmp    our_isr_return
  362. send_pkt_1:
  363.     jmp    our_isr_error
  364.  
  365.  
  366. f_terminate:
  367. ;
  368. ; Now disable interrupts
  369. ;
  370.     mov    al,int_no
  371.     call    maskint
  372.  
  373. ;
  374. ; Now return the interrupt to their handler.
  375. ;
  376.     mov    ah,25h            ;get the old interrupt into es:bx
  377.     mov    al,int_no
  378.     add    al,8
  379.     cmp    al,8+8            ;is it a slave 8259 interrupt?
  380.     jb    terminate_1        ;no.
  381.     add    al,70h - 8 - 8        ;map it to the real interrupt.
  382. terminate_1:
  383.     push    ds
  384.     lds    dx,their_recv_isr
  385.     int    21h
  386.     pop    ds
  387.  
  388.     mov    al,packet_int_no    ;release our_isr.
  389.     mov    ah,25h
  390.     push    ds
  391.     lds    dx,their_isr
  392.     int    21h
  393.     pop    ds
  394.  
  395. ;
  396. ; Now free our memory
  397. ;
  398.     push    cs
  399.     pop    es
  400.     mov    ah,49h
  401.     int    21h
  402.  
  403.     jmp    our_isr_return
  404.  
  405.  
  406. f_get_address:
  407.     call    verify_handle
  408. ;    mov    es,_ES[bp]        ; get new one
  409. ;    mov    di,_DI[bp]        ; get pointer, es:di is ready
  410. ;    mov    cx,_CX[bp]        ;Tell them how much room they have.
  411.     call    get_address
  412.     jc    get_address_space    ;no.
  413.     mov    _CX[bp],cx        ;Tell them how long our address is.
  414.     jmp    our_isr_return
  415.  
  416. get_address_space:
  417.     mov    dh,NO_SPACE
  418.     jmp    our_isr_error
  419.  
  420.  
  421. f_reset_interface:
  422.     call    verify_handle
  423.     call    reset_interface
  424.     jmp    our_isr_return
  425.  
  426.  
  427. verify_handle:
  428. ;Ensure that their handle is real.  Jump to our_isr_error if it
  429. ;isn't real.
  430.     mov    bx,_BX[bp]        ;is this handle in range?
  431.     cmp    bx,offset handles
  432.     jb    verify_handle_bad    ;no - must be bad.
  433.     cmp    bx,offset end_handles
  434.     jae    verify_handle_bad    ;no - must be bad.
  435.     cmp    [bx].in_use,0        ;if it's not in use, it's bad.
  436.     je    verify_handle_bad
  437.     ret
  438. verify_handle_bad:
  439.     mov    dh,BAD_HANDLE
  440.     add    sp,2            ;pop off our return address.
  441.     jmp    our_isr_error
  442.  
  443.  
  444.     public    set_recv_isr
  445. set_recv_isr:
  446.     mov    ah,35h            ;get the old interrupt into es:bx
  447.     mov    al,int_no
  448.     add    al,8
  449.     cmp    al,8+8            ;is it a slave 8259 interrupt?
  450.     jb    set_recv_isr_1        ;no.
  451.     add    al,70h - 8 - 8        ;map it to the real interrupt.
  452. set_recv_isr_1:
  453.     int    21h
  454.     mov    their_recv_isr.offs,bx
  455.     mov    their_recv_isr.segm,es
  456.  
  457.     mov    ah,25h            ;now set our recv interrupt.
  458.     mov    dx,offset recv_isr
  459.     int    21h
  460. ;
  461. ; Now enable interrupts
  462. ;
  463.     mov    al,int_no
  464.     call    unmaskint
  465.  
  466.     ret
  467.  
  468. their_recv_isr    dd    ?
  469.  
  470. recv_isr:
  471.     push    ax
  472.     push    ds
  473.     mov    ax,cs            ;ds = cs.
  474.     mov    ds,ax
  475.  
  476.     mov    savesp,sp
  477.     mov    savess,ss
  478.  
  479.     mov    ss,ax
  480.     mov    sp,offset stack
  481.  
  482.     push    bx
  483.     push    cx
  484.     push    dx
  485.     push    si
  486.     push    di
  487.     push    bp
  488.     push    es
  489.  
  490.     call    recv
  491.  
  492. ;
  493. ; The following code is ruthlessly stolen from Phil Karn's NET package.
  494. ;
  495.     cmp    is_at,1
  496.     jnz    recv_isr_3    ; Only one 8259, so skip this stuff
  497.     mov    al,0bh        ; read in-service register from
  498.     out    0a0h,al        ; secondary 8259
  499.     nop            ; settling delay
  500.     nop
  501.     nop
  502.     in    al,0a0h        ; get it
  503.     or    al,al        ; Any bits set?
  504.     jz    recv_isr_3    ; nope, not a secondary interrupt
  505.     mov    al,20h        ; Get EOI instruction
  506.     out    0a0h,al        ; Secondary 8259 (PC/AT only)
  507. recv_isr_3:
  508.     mov    al,20h            ;acknowledge the interrupt.
  509.     out    20h,al
  510.  
  511.     pop    es
  512.     pop    bp
  513.     pop    di
  514.     pop    si
  515.     pop    dx
  516.     pop    cx
  517.     pop    bx
  518.  
  519.     mov    ss,savess
  520.     mov    sp,savesp
  521.  
  522.     pop    ds
  523.     pop    ax
  524.     iret
  525.  
  526.  
  527. maskint:
  528.     mov    dx,21h            ;assume the master 8259.
  529.     cmp    al,8            ;using the slave 8259 on an AT?
  530.     jb    mask_not_irq2
  531.     mov    dx,0a1h            ;go enable it on slave 8259
  532.     sub    al,8
  533. mask_not_irq2:
  534.     mov    cl,al
  535.  
  536.     in    al,dx            ;enable interrupts on the master 8259.
  537.     mov    ah,1            ;clear the bit.
  538.     shl    ah,cl
  539.     or    al,ah
  540.     out    dx,al
  541.  
  542.     ret
  543.  
  544.  
  545. unmaskint:
  546.     mov    dx,21h            ;assume the master 8259.
  547.     cmp    al,8            ;using the slave 8259 on an AT?
  548.     jb    unmask_not_irq2
  549.     mov    dx,0a1h            ;go enable it on slave 8259
  550.     sub    al,8
  551. unmask_not_irq2:
  552.     mov    cl,al
  553.  
  554.     in    al,dx            ;enable interrupts on the master 8259.
  555.     mov    ah,1            ;clear the bit.
  556.     shl    ah,cl
  557.     not    ah
  558.     and    al,ah
  559.     out    dx,al
  560.  
  561.     ret
  562.  
  563.  
  564.     public    recv_find
  565. recv_find:
  566. ;called when we want to determine what to do with a received packet.
  567. ;enter with cx = packet length, es:di -> packet type.
  568.     assume    ds:code, es:nothing
  569.     push    cx
  570.  
  571.     mov    bx,offset handles
  572. recv_find_1:
  573.     cmp    [bx].in_use,0        ;is this handle in use?
  574.     je    recv_find_2        ;no - don't check the type.
  575.     mov    ax,[bx].receiver.offs    ;do they have a receiver?
  576.     or    ax,[bx].receiver.segm
  577.     je    recv_find_2        ;no - they're not serious about it.
  578.     mov    cx,[bx].packet_type_len    ;compare the packets.
  579.     lea    si,[bx].packet_type
  580.     or    cx,cx            ;in case cx is zero.
  581.     push    di
  582.     repe    cmpsb
  583.     pop    di
  584.     je    recv_find_3        ;we've got it!
  585. recv_find_2:
  586.     add    bx,(size per_handle)    ;go to the next handle.
  587.     cmp    bx,offset end_handles
  588.     jb    recv_find_1
  589.  
  590.     linc    packets_dropped
  591.  
  592.     pop    cx            ;we didn't find it -- discard it.
  593.     xor    di,di            ;"return" a null pointer.
  594.     mov    es,di
  595.     jmp    short recv_find_4
  596. recv_find_3:
  597.     pop    cx            ; the packet_length
  598.  
  599.     linc    packets_in
  600.     add    bytes_in.offs,cx    ;add up the received bytes.
  601.     adc    bytes_in.segm,0
  602.  
  603.     mov    found_handle,bx        ;remember what our handle was.
  604.     mov    ax,0            ;allocate request.
  605.     call    [bx].receiver        ;ask the client for a buffer.
  606. recv_find_4:
  607.     ret
  608.  
  609.  
  610.     public    recv_copy
  611. recv_copy:
  612. ;called after we have copied the packet into the buffer.
  613. ;enter with ds:si ->the packet, cx = length of the packet.
  614.     assume    ds:nothing, es:nothing
  615.     push    bx
  616.     mov    bx,found_handle
  617.     mov    ax,1            ;store request.
  618.     call    code:[bx].receiver
  619.     pop    bx
  620.     ret
  621.  
  622. code    ends
  623.  
  624.     end    start
  625.